classdef ReceiverSimulator < matlab.System
    % 接收机模拟器：集成信号接收、初始同步、跟踪及数据解调功能
    % 支持多频段GNSS信号处理，输出同步与跟踪性能指标
    % 专为多天线旋转载体GPS信号接收系统设计，包含五个环路协同工作

    properties (Access = private)
        Config              % 配置参数结构体
        signalSource        % 信号源（波形生成器）
        initSync            % 初始同步模块
        nonRotatingTracker  % 非旋转载波成分跟踪器
        rotatingTracker     % 旋转载波成分跟踪器
        rotationFreqTracker % 旋转频率跟踪器
        codeTracker         % 码跟踪环路
        antennaMerger       % 多天线合并模块
        buffer              % 信号缓存队列
        nSamplesPerInteg    % 每积分周期的采样数
        nFrames             % 跟踪帧数
        results             % 仿真结果存储结构体
        motionModel         % 运动模型（旋转载体）
        sampleRate          % 采样率
        carrierFreq         % 载波频率
        codeRate            % 码速率
    end

    methods(Access = public)
        function obj = ReceiverSimulator(Config)
            % 初始化接收机模拟器
            obj.Config = Config;
            obj.sampleRate = Config.waveform.sampleRate;
            
            % 获取载波频率和码速率
            bandToTrack = Config.tracker.bandToTrack;
            branchToTrack = Config.tracker.branchToTrack;
            bandName = ['band', num2str(bandToTrack)];
            obj.carrierFreq = Config.waveform.(bandName).(branchToTrack).carrierFreq;
            obj.codeRate = Config.waveform.(bandName).(branchToTrack).codeRate;
            
            % 初始化信号源
            obj.signalSource = SignalModulator(Config);
            
            % 初始化运动模型
            if isfield(Config, 'motionModel')
                obj.motionModel = MotionModel(Config.motionModel);
            end
            
            % 初始化缓存
            obj.buffer = Deque(0, Config.waveform.nBands, false);
            
            % 初始化各跟踪环路
            obj.initTrackingLoops(Config);
            
            % 计算时间相关参数
            obj.nSamplesPerInteg = floor(obj.sampleRate * Config.tracker.totalIntegTime);
            obj.nFrames = Config.sim.nFrames;
            
            % 初始化结果结构体
            obj.results = obj.initResults();
            
            % 重置所有组件
            obj.reset();
        end

        function reset(obj)
            % 重置接收机状态
            obj.signalSource.reset();
            if ~isempty(obj.motionModel)
                obj.motionModel.reset();
            end
            
            % 重置各跟踪环路
            if isfield(obj, 'nonRotatingTracker') && ~isempty(obj.nonRotatingTracker)
                obj.nonRotatingTracker.reset();
            end
            if isfield(obj, 'rotatingTracker') && ~isempty(obj.rotatingTracker)
                obj.rotatingTracker.reset();
            end
            if isfield(obj, 'rotationFreqTracker') && ~isempty(obj.rotationFreqTracker)
                obj.rotationFreqTracker.reset();
            end
            if isfield(obj, 'codeTracker') && ~isempty(obj.codeTracker)
                obj.codeTracker.reset();
            end
            
            obj.buffer.reset();
            obj.results = obj.initResults();
        end

        function simOut = run(obj)
            % 运行接收机仿真流程（初始同步→跟踪）
            simOut = struct();
            
            % 初始化结果存储
            simOut.initsync.prnid = NaN(1, obj.Config.sim.nMonteCarlo);
            simOut.initsync.delay = NaN(1, obj.Config.sim.nMonteCarlo);
            simOut.initsync.fqy = NaN(1, obj.Config.sim.nMonteCarlo);
            simOut.initsync.detected = NaN(1, obj.Config.sim.nMonteCarlo);
            
            simOut.tracker.delay = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.ph = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.fqy = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.rotfqy = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.delayerr = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.pherr = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.fqyerr = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.cn0 = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.lockStatus = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.tMeasure = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            simOut.tracker.steptime = NaN(obj.nFrames, obj.Config.sim.nMonteCarlo);
            
            disableInitSync = false;
            if isfield(obj.Config.initsync, 'disable')
                disableInitSync = strcmpi(obj.Config.initsync.disable, 'true');
            end
            
            for iMC = 1 : obj.Config.sim.nMonteCarlo
                obj.reset();
                
                % 1. 初始同步
                if disableInitSync
                    % 使用配置的初始值，跳过实际同步
                    syncInfo.prnid = obj.Config.waveform.prnid;
                    syncInfo.delay = obj.Config.initsync.delayInit;
                    syncInfo.doppler = obj.Config.initsync.fqyInit;
                    syncInfo.success = true;
                    syncInfo.time = 0;
                    
                    % 初始化各跟踪环路
                    obj.initTrackerLoops(syncInfo.time, syncInfo.prnid, syncInfo.delay, syncInfo.doppler);
                else
                    % 执行实际的初始同步
                    [syncSuccess, syncInfo] = obj.runInitialSync();
                    if ~syncSuccess
                        warning(['蒙特卡洛试验 ', num2str(iMC), ' 初始同步失败，跳过跟踪']);
                        simOut.initsync.detected(iMC) = 0;
                        continue;
                    end
                end
                
                % 保存同步结果
                simOut.initsync.prnid(iMC) = syncInfo.prnid;
                simOut.initsync.delay(iMC) = syncInfo.delay;
                simOut.initsync.fqy(iMC) = syncInfo.doppler;
                simOut.initsync.detected(iMC) = logical(syncInfo.success);
                
                % 2. 执行跟踪流程
                [trackResults, genieTrack] = obj.runTracking(syncInfo);
                
                % 3. 保存跟踪结果
                for iFrame = 1 : obj.nFrames
                    if iFrame <= length(trackResults)
                        simOut.tracker.delay(iFrame, iMC) = trackResults(iFrame).delay;
                        simOut.tracker.ph(iFrame, iMC) = trackResults(iFrame).carrierPhase;
                        simOut.tracker.fqy(iFrame, iMC) = trackResults(iFrame).doppler;
                        simOut.tracker.rotfqy(iFrame, iMC) = trackResults(iFrame).rotationFreq;
                        simOut.tracker.delayerr(iFrame, iMC) = trackResults(iFrame).delayErr;
                        simOut.tracker.pherr(iFrame, iMC) = trackResults(iFrame).phaseErr;
                        simOut.tracker.fqyerr(iFrame, iMC) = trackResults(iFrame).dopplerErr;
                        simOut.tracker.cn0(iFrame, iMC) = trackResults(iFrame).cn0;
                        simOut.tracker.lockStatus(iFrame, iMC) = trackResults(iFrame).lockStatus;
                        simOut.tracker.tMeasure(iFrame, iMC) = trackResults(iFrame).time;
                        simOut.tracker.steptime(iFrame, iMC) = trackResults(iFrame).stepTime;
                    end
                end
            end
            
            % 保存结果到对象属性
            obj.results = simOut;
        end

        function results = getResults(obj)
            % 获取仿真结果
            results = obj.results;
        end
    end

    methods(Access = private)
        function initTrackingLoops(obj, Config)
            % 初始化五个跟踪环路
            
            % 1. 非旋转载波成分跟踪器
            nonRotatingConfig = Config.tracker.nonRotatingCarrier;
            obj.nonRotatingTracker = CarrierTrackingLoop(nonRotatingConfig);
            
            % 2. 旋转载波成分跟踪器
            rotatingConfig = Config.tracker.rotatingCarrier;
            obj.rotatingTracker = CarrierTrackingLoop(rotatingConfig);
            
            % 3. 旋转频率跟踪器
            rotFreqConfig = Config.tracker.rotationFrequency;
            obj.rotationFreqTracker = RotationFrequencyTracker(rotFreqConfig);
            
            % 4. 码跟踪环路
            codeConfig = Config.tracker.code;
            obj.codeTracker = CodeTrackingLoop(codeConfig);
            
            % 5. 多天线合并模块
            obj.antennaMerger = helperMultiAntennaMerger(Config);
        end

        function initTrackerLoops(obj, tInit, prnid, initialDelay, initialDoppler)
            % 初始化各跟踪环路状态
            
            % 初始化码跟踪器
            obj.codeTracker.init(prnid, initialDelay);
            
            % 初始化载波跟踪器
            obj.nonRotatingTracker.init(initialDoppler, 0);
            obj.rotatingTracker.init(0, 0);
            
            % 初始化旋转频率跟踪器
            obj.rotationFreqTracker.init();
        end

        function results = initResults(obj)
            % 初始化结果结构体
            results = struct();
            results.initsync = struct();
            results.tracking = struct();
        end

        function [success, syncInfo] = runInitialSync(obj)
            % 执行初始同步
            syncInfo = struct();
            totalIntegTime = obj.Config.initsync.totalIntegTime;
            
            % 获取同步所需信号
            [waveform, tSync] = obj.signalSource(totalIntegTime);
            
            % 执行初始捕获（这里简化实现，实际项目中可使用更复杂的捕获算法）
            [prnid, delay, doppler, cn0] = obj.performAcquisition(waveform, totalIntegTime);
            
            % 解析同步结果
            syncInfo.prnid = prnid;
            syncInfo.doppler = doppler;
            syncInfo.delay = delay;
            syncInfo.cn0 = cn0;
            syncInfo.time = tSync;
            syncInfo.success = ~isnan(prnid);
            
            % 同步成功则初始化跟踪器
            if syncInfo.success
                obj.initTrackerLoops(syncInfo.time, syncInfo.prnid, syncInfo.delay, syncInfo.doppler);
                obj.buffer.pushBack(waveform); % 缓存同步信号用于跟踪
            end
            
            success = syncInfo.success;
        end

        function [prnid, delay, doppler, cn0] = performAcquisition(obj, waveform, integTime)
            % 简化的捕获实现
            % 在实际项目中，这里应该实现更复杂的延迟-多普勒二维搜索
            
            % 这里使用配置中的PRN作为捕获结果
            prnid = obj.Config.waveform.prnid;
            
            % 假设初始延迟和多普勒已知
            delay = obj.Config.initsync.delayInit;
            doppler = obj.Config.initsync.fqyInit;
            
            % 估计CN0
            sigPower = mean(abs(waveform(:)).^2);
            noisePower = obj.Config.waveform.k * obj.Config.waveform.T * obj.sampleRate;
            cn0 = 10*log10(sigPower/noisePower);
        end

        function [trackResults, genieTrack] = runTracking(obj, syncInfo)
            % 执行跟踪流程，包含五个环路的协同工作
            trackResults = repmat(struct(), obj.nFrames, 1);
            genieTrack = repmat(struct(), obj.nFrames, 1);
            
            % 进度显示
            progress = ProgressDisplayer('跟踪进度: ', obj.nFrames, 100, false);
            progress.start();
            
            iFrameProcessed = 0;
            currentTime = syncInfo.time;
            
            while iFrameProcessed < obj.nFrames
                % 确保缓存有足够数据
                while obj.buffer.size() < obj.nSamplesPerInteg
                    integTime = obj.Config.tracker.totalIntegTime;
                    [waveform, tWave] = obj.signalSource(integTime);
                    obj.buffer.pushBack(waveform);
                end
                
                % 提取一帧数据进行跟踪
                waveformFrame = obj.buffer.popFront(obj.nSamplesPerInteg);
                stepTime = obj.Config.tracker.totalIntegTime;
                
                % 1. 码跟踪处理
                [delayErr, currentDelay, corrVals] = obj.codeTracker(waveformFrame, stepTime);
                
                % 2. 多天线预处理与合并
                [mergedSignal, antennaWeights] = obj.antennaMerger(waveformFrame, corrVals);
                
                % 3. 旋转频率跟踪
                [rotFreqErr, currentRotFreq] = obj.rotationFrequencyTracker(mergedSignal, stepTime);
                
                % 4. 旋转载波成分跟踪
                [iqRotDeselected, rotPhaseErr, rotFreqErrDetail, rotLockStatus] = ...
                    obj.rotatingTracker(mergedSignal, stepTime);
                
                % 5. 非旋转载波成分跟踪
                [iqNonRotDeselected, nonRotPhaseErr, nonRotFreqErr, nonRotLockStatus] = ...
                    obj.nonRotatingTracker(iqRotDeselected, stepTime);
                
                % 6. 信号合并与CN0估计
                combinedSignal = iqNonRotDeselected;
                cn0Est = obj.estimateCN0(combinedSignal, stepTime);
                
                % 7. 计算锁定状态
                isLocked = nonRotLockStatus.isLocked && rotLockStatus.isLocked && (cn0Est > 30);
                
                % 8. 获取真值（用于评估）
                [geniePhase, genieFreq, genieDelay, genieCn0] = obj.getGenieTrack(currentTime);
                
                % 9. 存储跟踪结果
                if ~isnan(delayErr)
                    iFrameProcessed = iFrameProcessed + 1;
                    
                    trackResults(iFrameProcessed).time = currentTime;
                    trackResults(iFrameProcessed).stepTime = stepTime;
                    trackResults(iFrameProcessed).delay = currentDelay;
                    trackResults(iFrameProcessed).delayErr = delayErr;
                    trackResults(iFrameProcessed).doppler = nonRotFreqErr + genieFreq;
                    trackResults(iFrameProcessed).dopplerErr = abs(nonRotFreqErr);
                    trackResults(iFrameProcessed).rotationFreq = currentRotFreq;
                    trackResults(iFrameProcessed).carrierPhase = mod(nonRotPhaseErr + geniePhase, 2*pi);
                    trackResults(iFrameProcessed).phaseErr = abs(nonRotPhaseErr);
                    trackResults(iFrameProcessed).cn0 = cn0Est;
                    trackResults(iFrameProcessed).lockStatus = isLocked;
                    
                    % 存储真值
                    genieTrack(iFrameProcessed).phase = geniePhase;
                    genieTrack(iFrameProcessed).freq = genieFreq;
                    genieTrack(iFrameProcessed).delay = genieDelay;
                    genieTrack(iFrameProcessed).cn0 = genieCn0;
                    
                    progress(1);
                end
                
                % 更新当前时间
                currentTime = currentTime + stepTime;
            end
        end

        function cn0 = estimateCN0(obj, signal, integTime)
            % 估计载噪比CN0 (dB-Hz)
            sigPower = mean(abs(signal).^2);
            noisePower = obj.Config.waveform.k * obj.Config.waveform.T;
            cn0 = 10*log10(sigPower/noisePower);
        end

        function [phaseGenie, freqGenie, delayGenie, cn0Genie] = getGenieTrack(obj, tMeasure)
            % 获取真值信息（用于跟踪性能评估）
            
            % 生成器多普勒和相位信息
            freqGenie = obj.Config.doppler.bias + obj.Config.doppler.rate * tMeasure;
            phaseGenie = 2 * pi * (obj.carrierFreq + freqGenie) * tMeasure;
            
            % 生成器延迟信息
            delayGenie = obj.Config.delay.bias + obj.Config.delay.rate * tMeasure;
            
            % 生成器CN0信息
            signalPower = db2pow(obj.Config.signal.power);
            noisePower = obj.Config.waveform.k * obj.Config.waveform.T;
            cn0Genie = 10*log10(signalPower/noisePower);
        end
    end
end

function merger = helperMultiAntennaMerger(Config)
    % 多天线合并辅助函数
    merger = struct();
    merger.type = Config.tracker.antennaMerger.type;
    merger.numAntennas = Config.waveform.numAntennas;
    
    % 合并函数句柄
    if strcmpi(merger.type, 'EGC') % 等增益合并
        merger.mergeFunc = @(waveform, corrVals) mean(waveform, 2);
    elseif strcmpi(merger.type, 'MRC') % 最大比合并
        merger.mergeFunc = @(waveform, corrVals) helperMRC(waveform, corrVals);
    else % 默认使用等增益合并
        merger.mergeFunc = @(waveform, corrVals) mean(waveform, 2);
    end
    
    % 重载函数调用运算符
    merger = class(merger, 'MultiAntennaMerger');
end

function [merged, weights] = helperMRC(waveform, corrVals)
    % 最大比合并实现
    numAntennas = size(waveform, 2);
    weights = ones(1, numAntennas);
    
    % 根据相关值计算权重
    if isfield(corrVals, 'prompt') && size(corrVals.prompt, 2) >= numAntennas
        for i = 1:numAntennas
            weights(i) = abs(corrVals.prompt(i));
        end
        % 归一化权重
        if sum(weights) > 0
            weights = weights / sum(weights);
        end
    end
    
    % 执行加权合并
    merged = waveform * weights';
end

% 为多天线合并器添加函数调用能力
function [mergedSignal, weights] = subsref(merger, s)
    if strcmp(s(1).type, '()') && length(s) == 1
        [waveform, corrVals] = s(1).subs{:};
        if isempty(corrVals)
            mergedSignal = merger.mergeFunc(waveform, struct());
            weights = ones(1, merger.numAntennas) / merger.numAntennas;
        else
            [mergedSignal, weights] = merger.mergeFunc(waveform, corrVals);
        end
    else
        error('不支持的操作');
    end
end
